import { getToken, setToken, removeToken, setTimeStamp } from '@/utils/auth.js'
import { login, getUserInfo, getUserDetailById } from '@/api/user'
import { resetRouter } from '@/router' // 在路由文件中引入重置路由的方法
const state = {
  // token: null // 在用户模块中定义存储token的变量
  token: getToken(), // 页面一打开先从cookie里面获取token
  userInfo: {} // 定义一个存储用户信息的的变量，是一个空对象，不要写成null,会对建林用户名的快捷访问有影响
}
const mutations = {
  // 定义修改token的方法
  setToken(state, token) {
    state.token = token // 修改state中的token
    setToken(token) // 调用存储cookie的方法，顺便在cookie中存储一份，防止用户刷新页面token丢失
  },
  removeToken(state) {
    // 当用户点击注销的时候清空token
    state.token = null
    // 同时清除cookie中缓存的cookie
    removeToken()
  },
  // 定义修改用户资料的方法， res 是后台返回的数据
  setUserInfo(state, res) {
    state.userInfo = res // 响应式的修改数据方式一
    // state.userInfo = { ...res } // 响应式的修改数据方式2，相当于浅拷贝
    // Vue.set('目标对象', key, value) //响应式的修改数据方式3
    // Object.assign({}, state.userInfo) // 响应式的修改数据方式4
    // state.userInfo.name = 'zs'  //这一种不属于响应式修改
  },
  // 定义清除用户信息的方法，用户退出登录的时候清除用户信息
  removeUserInfo(state) {
    state.userInfo = {}
  }
}
const actions = {
  // 获取登录接口
  // 第一种方式
  async login(context, data) {
    const res = await login(data)
    // 由于在响应拦截器里面已经对数据进行了解构，而且已经对success进行了判断，所以不在进行判断
    // 判断响应状态，值为布尔值
    // 把接口请求回来的数据更新到state中
    // actions 修改state 必须通过mutations
    context.commit('setToken', res)
    // 代码执行到这里证明已经获取了token，登录成功了，在存储token的同时，存储当前的时间戳
    setTimeStamp() // 调用存储时间戳的方法
  },
  // 第二种方式
  // 为什么async/await 不用返回new Promise,因为 async函数本身就是 Promise,promise的值返回的值
  // login(context, data) {
  //   return new Promise(function(resolve) {
  //     login(data).then(result => {
  //       if (result.data.success) {
  //         context.commit('setToken', result.data.data) // 提交mutations设置token
  //         resolve() // 表示执行成功了
  //       }
  //     })
  //   })
  // }
  // 获取用户信息actions
  async getUserInfo(context) {
    const res = await getUserInfo() // 调用接口，获取用户资料信息
    // 获取用户头像的接口需要传送用户信息的userId
    const baseInfo = await getUserDetailById(res.userId)
    // 将后台返回的数据更新到state中的userInfo变量里，必须经过mutations里面的方法
    // 合并头像数据
    const baseRes = { ...res, ...baseInfo }
    // context.commit('setUserInfo', res)
    context.commit('setUserInfo', baseRes)
    return res // 后面调用用户信息的用
  },
  // 登出操作
  logout(contxet) {
    // 退出登录，将token清空，并清空用户信息，直接调用mutations里面的方法
    contxet.commit('removeToken')
    contxet.commit('removeUserInfo')
    // 退出登录的时候重置路由
    resetRouter()
    // 退出登录的时候需要将Vuex中存储的路由信息重置到只有静态路由的数据
    // 在Vuex中的子模块如何调用另外一个子模块中方法
    // 1. 没有开启命名空间的情况下，模块中方法都是暴露在全局的，可以直接调用
    // 2. 开启命名空间的情况下 需要加 root: true 代表可以访问全局模块的方法
    // 调用permission模块中的setRoutes 方法
    contxet.commit('permission/setRoutes', [], { root: true })
  }
}
export default {
  namespaced: true, // 开启命名空间
  state,
  mutations,
  actions
}
